package com.tools.middle.mq;

import com.tools.common.container.AbsOwnList;
import com.tools.common.container.AbsOwnSet;
import com.tools.common.container.SetEnum;
import com.tools.common.exception.NotFoundDataException;
import com.tools.common.io.HostNode;
import com.tools.common.object.Note;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;

/**
 * 消息队列的配置项包装类
 * */
@Note("消息队列的配置项包装类")
public class MQSource {

    @Note("消息队列的服务器配置（一个是单节点，也可以是集群）")
    private LinkedHashSet<HostNode> hostNodeSet;


    /* *************************************************************************************************
     *
     *          构造器
     *
     * *************************************************************************************************
     * */

    public MQSource() {}
    
    public static MQSource of() {
        return new MQSource();
    }

    @Note("读取 properties 里的配置项，转为实例返回")
    public static MQSource from(Map properties) {
        MQSource source = new MQSource();
        if(properties == null || properties.isEmpty()) return source;
        
        return source;
    }

    /* *************************************************************************************************
     *
     *          Getter / Setter
     *
     * *************************************************************************************************
     * */

    public void setHostNodeSet(LinkedHashSet<HostNode> hostNodeSet) {
        if(hostNodeSet == null || hostNodeSet.isEmpty()) {
            throw new IllegalArgumentException("至少需要配置一个以上的节点");
        }
        this.hostNodeSet = hostNodeSet;
    }

    /* **********************************************************************************
     *
     *          链式调用
     *
     * *********************************************************************************
     * */

    public MQSource hostNodeSet(LinkedHashSet<HostNode> hostNodeSet) {
        this.setHostNodeSet(hostNodeSet);
        return this;
    }


    /* **********************************************************************************
     *
     *          自定义方法
     *
     * *********************************************************************************
     * */

    public MQSource add(String hostAndPort) {
        this.private_initHostNodeSet(1);
        this.hostNodeSet.add(new HostNode(hostAndPort));
        return this;
    }

    public MQSource add(HostNode node) {
        if(node == null) throw new NullPointerException("MQ 主机节点实例不能为 null");
        this.private_initHostNodeSet(1);
        this.hostNodeSet.add(node);
        return this;
    }

    public MQSource addAll(String... hostNodeArray) {
        if(hostNodeArray == null) return this;
        int length = hostNodeArray.length;
        if(length == 0) return this;
        this.private_initHostNodeSet(length);
        for(String hostAndPort : hostNodeArray) {
            this.hostNodeSet.add(new HostNode(hostAndPort));
        }
        return this;
    }

    public MQSource addAll(HostNode... hostNodeArray) {
        if(hostNodeArray == null) return this;
        int length = hostNodeArray.length;
        if(length == 0) return this;
        this.private_initHostNodeSet(length);
        for(HostNode node : hostNodeArray) {
            if(node == null) throw new NullPointerException("MQ 主机节点实例不能为 null");
            this.hostNodeSet.add(node);
        }
        return this;
    }


    public MQSource addAllString(List<String> hostAndPortList) {
        if(hostAndPortList == null || hostAndPortList.isEmpty()) return this;
        this.private_initHostNodeSet(hostAndPortList.size());
        for(String hostAndPort : hostAndPortList) {
            this.hostNodeSet.add(new HostNode(hostAndPort));
        }
        return this;
    }

    public MQSource addAllNode(List<HostNode> hostAndPortList) {
        if(hostAndPortList == null || hostAndPortList.isEmpty()) return this;
        this.private_initHostNodeSet(hostAndPortList.size());
        for(HostNode node : hostAndPortList) {
            if(node == null) throw new NullPointerException("MQ 主机节点实例不能为 null");
            this.hostNodeSet.add(node);
        }
        return this;
    }


    public MQSource addAllString(AbsOwnList<String> hostAndPortList) {
        if(hostAndPortList != null && !hostAndPortList.isEmpty()) {
            this.private_initHostNodeSet(hostAndPortList.size());
            for(String hostAndPort : hostAndPortList) {
                this.hostNodeSet.add(new HostNode(hostAndPort));
            }
        }
        return this;
    }

    public MQSource addAllNode(AbsOwnList<HostNode> hostAndPortList) {
        if(hostAndPortList != null && !hostAndPortList.isEmpty()) {
            this.private_initHostNodeSet(hostAndPortList.size());
            for(HostNode node : hostAndPortList) {
                if(node == null) throw new NullPointerException("MQ 主机节点实例不能为 null");
                this.hostNodeSet.add(node);
            }
        }
        return this;
    }


    public MQSource addAllString(LinkedHashSet<String> hostNodeSet) {
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return this;
        this.private_initHostNodeSet(hostNodeSet.size());
        for(String hostAndPort : hostNodeSet) {
            this.hostNodeSet.add(new HostNode(hostAndPort));
        }
        return this;
    }

    public MQSource addAllNode(LinkedHashSet<HostNode> hostNodeSet) {
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return this;
        this.private_initHostNodeSet(hostNodeSet.size());
        for(HostNode node : hostNodeSet) {
            if(node != null) {
                this.hostNodeSet.add(node);
                continue;
            }
            throw new NullPointerException("MQ 主机节点实例不能为 null");
        }
        return this;
    }

    public MQSource addAllString(AbsOwnSet<String> hostNodeSet) {
        if(hostNodeSet == null || hostNodeSet.isEmpty() || hostNodeSet.getImplEnum() != SetEnum.LINKED) return this;
        this.private_initHostNodeSet(hostNodeSet.size());
        for(String hostAndPort : hostNodeSet) {
            this.hostNodeSet.add(new HostNode(hostAndPort));
        }
        return this;
    }

    public MQSource addAllNode(AbsOwnSet<HostNode> hostNodeSet) {
        if(hostNodeSet == null || hostNodeSet.isEmpty() || hostNodeSet.getImplEnum() != SetEnum.LINKED) return this;
        this.private_initHostNodeSet(hostNodeSet.size());
        for(HostNode node : hostNodeSet) {
            if(node != null) {
                this.hostNodeSet.add(node);
                continue;
            }
            throw new NullPointerException("MQ 主机节点实例不能为 null");
        }
        return this;
    }


    public MQSource remove(String hostAndPort) {
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return this;
        this.hostNodeSet.remove(new HostNode(hostAndPort));
        return this;
    }

    public MQSource remove(HostNode node) {
        if(node == null) return this;
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return this;
        this.hostNodeSet.remove(node);
        return this;
    }


    public MQSource removeAll(String... hostNodeArray) {
        if(hostNodeArray == null || hostNodeArray.length == 0) return this;
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return this;
        for (String hostAndPort : hostNodeArray) {
            this.hostNodeSet.remove(hostAndPort);
        }
        return this;
    }

    public MQSource removeAll(HostNode... hostNodeArray) {
        if(hostNodeArray == null || hostNodeArray.length == 0) return this;
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return this;
        for (HostNode node : hostNodeArray) {
            this.hostNodeSet.remove(node);
        }
        return this;
    }

    public MQSource removeAllString(Iterable<String> hostNodeArray) {
        if(hostNodeArray == null) return this;
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return this;
        for (String hostAndPort : hostNodeArray) {
            this.hostNodeSet.remove(hostAndPort);
        }
        return this;
    }

    public MQSource removeAllNode(Iterable<HostNode> hostNodeArray) {
        if(hostNodeArray == null) return this;
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return this;
        for (HostNode node : hostNodeArray) {
            this.hostNodeSet.remove(node);
        }
        return this;
    }


    public boolean contains(String hostAndPort) {
        if(hostAndPort == null || hostAndPort.isEmpty()) return false;
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return false;
        return hostNodeSet.contains(hostAndPort);
    }

    public boolean contains(HostNode hostAndPort) {
        if(hostAndPort == null) return false;
        if(hostNodeSet == null || hostNodeSet.isEmpty()) return false;
        return hostNodeSet.contains(hostAndPort);
    }

    public HostNode firstNode() {
        if(hostNodeSet == null || hostNodeSet.isEmpty()) throw new NotFoundDataException("没有找到 MQ 节点");
        return hostNodeSet.iterator().next();
    }


    /* *************************************************************************************************
     *
     *          私有逻辑
     *
     * *************************************************************************************************
     * */

    @Note("初始化节点集合")
    private void private_initHostNodeSet(int initSize) {
        if(hostNodeSet == null) {
            this.hostNodeSet = new LinkedHashSet<>((int) (initSize / 0.75) + 1);
        }
    }
}
